package com.thundern.tdcrawler.service.job;

import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.thundern.tdcrawler.executor.CountableThreadPool;
import com.thundern.tdcrawler.model.Request;
import com.thundern.tdcrawler.model.Site;

public abstract class SpiderJob implements Job, ApplicationContextAware {

	Logger logger = LoggerFactory.getLogger(this.getClass());

//	private PageDownloadTask downloadTask;
//
//	private PageParserTask pageParserTask;
//		
//	private List<Pipeline> pipelines;
//
//	private Request startRequest;
	
	protected AtomicInteger stat;
	
	protected final static int STAT_INIT = 0;

	protected final static int STAT_RUNNING = 1;

	protected final static int STAT_STOPPED = 2;
	
	protected boolean exitWhenComplete = true;
	protected boolean spawnUrl = true;

    protected boolean destroyWhenExit = true;

    protected ReentrantLock newUrlLock = new ReentrantLock();

    protected Condition newUrlCondition = newUrlLock.newCondition();
    
    protected int emptySleepTime = 30000;
    protected final AtomicLong pageCount = new AtomicLong(0);
	protected ApplicationContext applicationContext;
	
	protected CountableThreadPool threadPool;
	
//	private Site site;
	
//	public SpiderJob() {}
//	public SpiderJob(Request startRequest) {
//		this.startRequest = startRequest;
//		this.downloadTask = new PageDownload();
//		this.pageParserTask = new OschinaBlogPageParser();
//		this.pipelines = new ArrayList<Pipeline>();
//	}		
	@PostConstruct
	public void initBase() {
		stat = new AtomicInteger(STAT_RUNNING);
	}
	
	protected void waitNewUrl() {
        newUrlLock.lock();
        try {
            //double check
            if (threadPool.getAliveThread() == 0 && exitWhenComplete) {
                return;
            }
            newUrlCondition.await(emptySleepTime, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            logger.warn("waitNewUrl - interrupted, error {}", e);
        } finally {
            newUrlLock.unlock();
        }
    }

	protected void signalNewUrl() {
        try {
            newUrlLock.lock();
            newUrlCondition.signalAll();
        } finally {
            newUrlLock.unlock();
        }
    }
    
	protected void onError(Request request) {
//        if (CollectionUtils.isNotEmpty(spiderListeners)) {
//            for (SpiderListener spiderListener : spiderListeners) {
//                spiderListener.onError(request);
//            }
//        }
    }

    protected void onSuccess(Request request) {
//        d
    }
	
	public abstract void doJob() ;

	public String getDomain() {
		return getSite().getDomain();
	}
	
	public String getUUID() {
		return UUID.fromString(getSite().getStartUrl()).toString();
	}
	
	public abstract Site getSite() ;

	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
	
}
